package org.farm2.service.controller;

import com.farm2.lucene.impl.Farm2LuceneSearchImpl;
import com.farm2.lucene.inter.Farm2LuceneSearchInter;
import com.farm2.lucene.query.DocumentQuery;
import com.farm2.lucene.query.rule.DocumentRuleByMultiField;
import com.farm2.lucene.query.rule.DocumentRuleByTerm;
import com.farm2.lucene.query.rule.DocumentRuleByVector;
import com.farm2.lucene.result.DocumentResult;
import com.farm2.lucene.utils.FarmLuceneUtils;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.farm2.base.domain.FarmUserContextLoader;
import org.farm2.llm.service.LlmClientServiceInter;
import org.farm2.service.dto.SearchDto;
import org.farm2.service.lucene.doc.enums.DocumentTitleEnum;
import org.farm2.service.lucene.doc.enums.IndexModelEnum;
import org.farm2.service.utils.FarmSearchAnalysisUtils;
import org.farm2.skc.domain.SkcKnow;
import org.farm2.skc.dto.web.WebKnowDto;
import org.farm2.skc.service.SkcKnowServiceInter;
import org.farm2.tools.db.DataQuery;
import org.farm2.tools.db.DataResult;
import org.farm2.tools.db.ResultDataHandle;
import org.farm2.tools.db.commons.DBRule;
import org.farm2.tools.db.commons.DBSort;
import org.farm2.tools.web.Farm2HtmlUtils;
import org.farm2.tools.web.FarmResponseCode;
import org.farm2.tools.web.FarmResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 知识
 *
 * @author cbtg自动生成  2025-2-4 12:13:51
 */
@RestController
@RequestMapping("/api/search")
public class WebSearchController {
    @Autowired
    private SkcKnowServiceInter skcKnowServiceImpl;
    @Autowired
    private LlmClientServiceInter llmClientServiceImpl;


    @Autowired
    private FarmSearchAnalysisUtils farmSearchAnalysisUtils;

    /**
     * 检索知识标题
     *
     * @return
     */
    @PreAuthorize("@farmAction.has('search.title')")
    @PostMapping("/title")
    public FarmResponseResult searchTitle(@Valid @RequestBody SearchDto searchDto) {
        String searchType = getSearchType(searchDto);
        Farm2LuceneSearchInter search = new Farm2LuceneSearchImpl(FarmLuceneUtils.getLuceneIndexFilePath());
        DocumentQuery query = new DocumentQuery();
        query.setPageSize(10);
        query.setPage(searchDto.getPage());
        query.addRule(new DocumentRuleByMultiField(List.of(DocumentTitleEnum.title.name()), searchDto.getWord()));
        return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, search.search(query));
    }





    /**
     * 全文检索知识
     *
     * @return
     */
    @PreAuthorize("@farmAction.has('search.do')")
    @PostMapping
    public FarmResponseResult search(@Valid @RequestBody SearchDto searchDto) {
        String searchType = getSearchType(searchDto);
        Farm2LuceneSearchInter search = new Farm2LuceneSearchImpl(FarmLuceneUtils.getLuceneIndexFilePath());
        DocumentQuery query = new DocumentQuery();
        query.setPageSize(10);
        query.setPage(searchDto.getPage());
        if (searchType.equals("EMBEDDING-ALL")) {

            DocumentResult result = new DocumentResult();
            try {
            query = new DocumentQuery();
            query.setPageSize(10);
            query.setPage(searchDto.getPage());
            search = new Farm2LuceneSearchImpl(FarmLuceneUtils.getLuceneEmbeddingFilePath());
            query.addRule(new DocumentRuleByVector(DocumentTitleEnum.embedding_vector.name(), llmClientServiceImpl.getEmbeddingClient().getEmbedding(searchDto.getWord()), 30));
                result = search.search(query);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, loadViewImg(result));
        }
        if (searchType.equals("LUCENE-ALL")) {

            if (searchDto.getModel() != null && !searchDto.getModel().equals("all")) {
                query.addRule(new DocumentRuleByTerm("model", searchDto.getModel()));
            }
            query.addRule(new DocumentRuleByMultiField(List.of(DocumentTitleEnum.title.name(), DocumentTitleEnum.tagTitles.name(), DocumentTitleEnum.text.name()), searchDto.getWord()));
            return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, loadViewImg(search.search(query)));
        }
        if (searchType.equals("LUCENE-TAG")) {

            if (searchDto.getModel() != null && !searchDto.getModel().equals("all")) {
                query.addRule(new DocumentRuleByTerm("model", searchDto.getModel()));
            }
            query.addRule(new DocumentRuleByMultiField(List.of(DocumentTitleEnum.tagTitles.name(), DocumentTitleEnum.tagKeys.name()), farmSearchAnalysisUtils.getTagKey(searchDto.getWord())));
            return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, loadViewImg(search.search(query)));
        }
        if (searchType.equals("MY")) {

            DataResult result = skcKnowServiceImpl.searchSkcKnow(DataQuery.getInstance()//
                    .addRule(new DBRule("CUSERKEY", FarmUserContextLoader.getCurrentUserKey(), "="))//
                    .addSort(new DBSort("ETIME", DBSort.SORT_TYPE.DESC))
                    .setPage(searchDto.getPage()).setPageSize(10)//
            );
            DocumentResult myresult = new DocumentResult(result, getKnowToIndexDic());
            myresult = loadKnow(myresult);
            myresult.setSearchTitle("我的知识");
            loadViewImg(myresult);
            return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, myresult);
        }
        if (searchType.equals("NEW")) {

            DataResult result = skcKnowServiceImpl.searchSkcKnow(DataQuery.getInstance()//
                    .addSort(new DBSort("ETIME", DBSort.SORT_TYPE.DESC))
                    .setPage(searchDto.getPage()).setPageSize(10)//
            );
            DocumentResult myresult = new DocumentResult(result, getKnowToIndexDic());
            myresult = loadKnow(myresult);
            myresult.setSearchTitle("最新知识");
            loadViewImg(myresult);
            return FarmResponseResult.getInstance(FarmResponseCode.SUCESS, myresult);
        }
        return FarmResponseResult.getInstance(FarmResponseCode.ERROR, "无对应检索类型");
    }


    /**
     * 加载知识的预览图
     *
     * @param result
     * @return
     */
    private DocumentResult loadViewImg(DocumentResult result) {
        result.runDataHandle(new ResultDataHandle() {
            @Override
            public void handle(Map<String, Object> row) {
                String knowid = (String) row.get(DocumentTitleEnum.knowId.name());
                String model = (String) row.get(DocumentTitleEnum.model.name());
                if (model != null && (
                        model.equals(IndexModelEnum.KNOW_DOC.name())
                                || model.equals(IndexModelEnum.EMBEDDING.name())
                )) {
                    if (knowid != null) {
                        List<String> imgids = skcKnowServiceImpl.getImgView(knowid);
                        if (imgids.size() > 0) {
                            if (imgids.size() > 5) {
                                row.put(DocumentTitleEnum.imgs.name(), String.join(",", imgids.subList(0, 5)));
                            } else {
                                row.put(DocumentTitleEnum.imgs.name(), String.join(",", imgids));
                            }
                        }
                    }
                }
            }
        });
        return result;
    }


    private DocumentResult loadKnow(DocumentResult myresult) {
        myresult.runDataHandle(new ResultDataHandle() {
            @Override
            public void handle(Map<String, Object> row) {
                row.put("id", row.get("knowId"));
                row.put(DocumentTitleEnum.model.name(), IndexModelEnum.KNOW_DOC.name());
                String knowid = (String) row.get("knowId");
                if (StringUtils.isNotBlank(knowid)) {
                    SkcKnow know = skcKnowServiceImpl.getSkcKnowById(knowid);
                    row.put(DocumentTitleEnum.text.name(), Farm2HtmlUtils.getTextByHtml(skcKnowServiceImpl.getKnowText(know), 128));
                    row.put(DocumentTitleEnum.tagTitles.name(), skcKnowServiceImpl.getKnowIndexTags(know).getTitles());
                }
            }
        });
        return myresult;
    }

    private Map<String, String> getKnowToIndexDic() {
        Map<String, String> knowToIndexDic = new HashMap<>();

        knowToIndexDic.put("NONE", DocumentTitleEnum.fileId.name());



        knowToIndexDic.put("ID", DocumentTitleEnum.knowId.name());




        knowToIndexDic.put("TITLE", DocumentTitleEnum.title.name());
        knowToIndexDic.put("ETIME", DocumentTitleEnum.etime.name());





        knowToIndexDic.put("CUSERKEY", DocumentTitleEnum.userKey.name());

        knowToIndexDic.put("EUSERNAME", DocumentTitleEnum.userName.name());
        return knowToIndexDic;
    }


    /**
     * 获得检索类型
     *
     * @param searchDto
     * @return
     */
    private String getSearchType(SearchDto searchDto) {
        String type = "LUCENE-ALL";
        if ("EMBEDDING".equals(searchDto.getModel())) {
            return "EMBEDDING-ALL";
        }
        if (searchDto.getWord().trim().equals("SYS-我的知识")) {

                type = "MY";
        } else if (searchDto.getWord().trim().equals("SYS-最新知识")) {

                type = "NEW";
        } else if (searchDto.getWord().trim().indexOf("TAG-") == 0) {
                type = "LUCENE-TAG";
        } else {
            type = "LUCENE-ALL";
        }
        return type;
    }

}
